package com.boe.server.register.security.filter;

import com.boe.server.register.config.JWTConfig;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.Jwts;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.stream.Collectors;

/**
 * JWT接口请求校验拦截器
 * 请求接口时会进入这里验证Token是否合法和过期
 *
 * @author uaniheng
 * @CreateTime 2019/10/5 16:41
 */
@Slf4j
public class JWTAuthenticationTokenFilter extends BasicAuthenticationFilter {

    private final JWTConfig jwtConfig;


    public JWTAuthenticationTokenFilter(AuthenticationManager authenticationManager, JWTConfig jwtConfig) {
        super(authenticationManager);
        this.jwtConfig = jwtConfig;
    }

    @Override
    @SuppressWarnings("unchecked")
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {
        // 获取请求头中JWT的Token
        String tokenHeader = request.getHeader(jwtConfig.getTokenHeader());
        if (null != tokenHeader && tokenHeader.startsWith(jwtConfig.getTokenPrefix())) {
            try {
                // 截取JWT前缀
                String token = tokenHeader.replace(jwtConfig.getTokenPrefix(), "");
                // 解析JWT
                Claims claims = Jwts.parser()
                        .setSigningKey(jwtConfig.getSecret())
                        .parseClaimsJws(token)
                        .getBody();
                // 获取用户名
                String username = claims.getSubject();
                String uuid = claims.getId();
                if (!StringUtils.isEmpty(username)) {
                    // 获取角色
                    List<String> authorities =
                            (List<String>) claims.get("authorities");
                    List<SimpleGrantedAuthority> authorityList = authorities.stream()
                            .map(SimpleGrantedAuthority::new)
                            .collect(Collectors.toList());
                    // 按约定此处token对象只能由provider提供，此处简化代码没有使用provider
                    UsernamePasswordAuthenticationToken authentication =
                            new UsernamePasswordAuthenticationToken(username, "", authorityList);
                    SecurityContextHolder.getContext().setAuthentication(authentication);
                }
            } catch (ExpiredJwtException e) {
                log.info("Token过期");
            } catch (Exception e) {
                e.printStackTrace();
                log.info("Token无效");
            }
        }
        filterChain.doFilter(request, response);
    }
}